package com.suny.example;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;

/**
 * 生产者消费者模型
 * @author sunny
 * @date 2019/4/28
 */
public class ProducerConsumerTest {
    public static void main(String[] args) {
        Store store = new Store(30);
        Consumer c1 = new Consumer(store, 50);
        Consumer c2 = new Consumer(store, 20);
        Consumer c3 = new Consumer(store, 30);
        Producer p1 = new Producer(store, 10);
        Producer p2 = new Producer(store, 10);
        Producer p3 = new Producer(store, 10);
        Producer p4 = new Producer(store, 10);
        Producer p5 = new Producer(store, 10);
        Producer p6 = new Producer(store, 10);
        Producer p7 = new Producer(store, 80);

        c1.start();
        c2.start();
        c3.start();
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
        p6.start();
        p7.start();

        ArrayList<Object> list = new ArrayList<>();

    }
}

@Data
@NoArgsConstructor
class Store {
    private static final int capacity = 100;
    private int currentNum;

    Store(int currentNum) {
        this.currentNum = currentNum;
    }

    /**
     * 生产方法
     *
     * @param num
     * @author sunny
     * @date 2019/4/28
     * @return void
     */
    public synchronized void produce(int num) {
        while (num + currentNum > capacity) {
            System.out.println("要生产的数量 " + num + " 超过可生产数量 " + (capacity - currentNum) + ", 暂无法生产!");
            try {
                wait();
            } catch (InterruptedException e) {

            }
        }

        currentNum += num;
        System.out.println("已经生产了 " + num + " 个产品, 现仓储量为: " + currentNum);

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyAll();
    }

    /**
     * 消费方法
     *
     * @param num
     * @author sunny
     * @date 2019/4/28
     * @return void
     */
    public synchronized void consume(int num) {
        while (currentNum < num) {
            try {
                wait();
            } catch (InterruptedException e) {

            }
        }

        currentNum -= num;
        System.out.println("已经消费了 " + num + " 个产品, 现仓储量为: " + currentNum);

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyAll();
    }
}

/**
 * 生产者
 *
 * @author sunny
 * @date 2019/4/28
 */
@Data
@AllArgsConstructor
class Producer extends Thread {
    private Store store;
    private int num;

    /**
     * 无限生产产品
     *
     * @author sunny
     * @date 2019/4/28
     * @return void
     */
    @Override
    public void run() {
        while (true) {
            store.produce(num);
        }
    }
}

/**
 * 消费者
 *
 * @author sunny
 * @date 2019/4/28
 */
@Data
@AllArgsConstructor
class Consumer extends Thread {
    private Store store;
    private int num;

    /**
     * 无限消费产品
     *
     * @author sunny
     * @date 2019/4/28
     * @return void
     */
    @Override
    public void run() {
        while (true) {
            store.consume(num);
        }
    }
}